#!/usr/bin/env python3

import time
import os

def getMap():
    m = [
        "#####################",
        "#     ##          #S#",
        "# ###  # ######## # #",
        "# #  # # ##    ## # #",
        "# ## # # ## ## ## # #",
        "# #  # # ##  # ## # #",
        "#   ## # ## ##    # #",
        "### ## # ########## #",
        "#E  ##              #",
        "#####################"]

    return [list(x) for x in m]

def showMap(mazeMap):
    print("\033[1;1H", end='', flush=True)
    for r in mazeMap:
        for c in r:
            print(c, end='')
        print()

def getPos(mazeMap, ch):
    for x, r in enumerate(mazeMap):
        for y, c in enumerate(r):
            if c == ch:
                return x, y
    return None

directs = ((0, 1), (1, 0), (-1, 0), (0, -1))

def maze(mazeMap, start, end):
    mazeMap[start[0]][start[1]] = '@'
    showMap(mazeMap)
    time.sleep(0.1)

    if start[0] == end[0] and start[1] == end[1]:
        os._exit(0)

    for dirs in directs:
        newPos = (start[0] + dirs[0], start[1] + dirs[1])
        if mazeMap[newPos[0]][newPos[1]] in '@#':
            continue
        maze(mazeMap, newPos, end)

    mazeMap[start[0]][start[1]] = ' '
    showMap(mazeMap)
    time.sleep(0.1)

def mazeFor(mazeMap, start, end):
    stack = [start]

    while True:
        cur = stack.pop()

        mazeMap[cur[0]][cur[1]] = '@'
        showMap(mazeMap)
        time.sleep(0.1)

        if cur[0] == end[0] and cur[1] == end[1]:
            break

        for dirs in directs:
            newPos = (cur[0] + dirs[0], cur[1] + dirs[1])
            if mazeMap[newPos[0]][newPos[1]] in '@#':
                continue
            stack.append(newPos)

def main():
    print("\033[2J", end='', flush=True)

    mazeMap = getMap()
    start = getPos(mazeMap, 'S')
    end = getPos(mazeMap, 'E')

    maze(mazeMap, start, end)
    #  mazeFor(mazeMap, start, end)

    return


if __name__ == "__main__":
    main()
